package cn.tedu.charging.order.service.impl;

import cn.tedu.charging.common.pojo.message.CheckResultMessage;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.order.dao.mapper.BillFailMapper;
import cn.tedu.charging.order.dao.repository.BillRepository;
import cn.tedu.charging.order.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.order.pojo.po.ChargingBillSuccessPO;
import cn.tedu.charging.order.service.ConsumerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * 消费的消息处理业务逻辑
 */
@Service
@Slf4j
public class ConsumerServiceImpl implements ConsumerService {
    @Autowired
    private BillRepository billRepository;


    //在设备自检反馈信息之后,业务处理的实现方法
    @Override
    public void handlerCheckResult(CheckResultMessage msg) {
        log.debug("处理设备自检消费业务,消息数据:{}", msg);
        //添加幂等处理方案 每次执行消费,先检查订单是否已经存在了,如果已存在说明消费消息重复执行的
        Boolean exists = billRepository.existsBill(msg.getOrderNo());
        if (exists) {
            log.info("消息重复消费,无需执行");
            return;
        }
        //1.从消息拿到result
        Boolean result = msg.getResult();
        if (result) {
            log.debug("设备自检成功");
            //2.组织封装success 写入数据库
            saveBillSuccess(msg);
            //TODO 3.组织通知用户的消息
        } else {
            log.debug("设备自检失败");
            //4.组织fail 写入数据库
            saveBillFail(msg);
            //5.调用设备服务修改设备的状态 TODO
            //TODO 6.组织失败消息推送给用户 走人sorry
        }
        //TODO 7.将不同分支的消息推送给用户端
    }

    private void saveBillFail(CheckResultMessage msg) {
        //1.组织ChargingBillFailPO 对应表 charging_bill_fail
        ChargingBillFailPO fail = new ChargingBillFailPO();
        //1.1从消息直接获取的属性
        fail.setBillId(msg.getOrderNo());
        fail.setFailDesc(msg.getFailDesc());
        fail.setUserId(msg.getUserId());
        fail.setGunId(msg.getGunId());
        //TODO 1.2冗余属性可以使用消息数据单独查询封装 operator_id station_id vehicle_id
        //1.3业务生成的默认值
        fail.setCreateTime(new Date());
        fail.setUpdateTime(fail.getCreateTime());
        fail.setDeleted(0);//逻辑删除字段
        //2.数据仓储层入口 写入失败
        billRepository.saveFailBill(fail);
    }

    private void saveBillSuccess(CheckResultMessage msg) {
        //1.组织ChargingBillSuccessPO 对应表 charging_bill_success
        ChargingBillSuccessPO success = new ChargingBillSuccessPO();
        //1.1从消息补充消息字段
        success.setUserId(msg.getUserId());
        success.setBillId(msg.getOrderNo());
        success.setGunId(msg.getGunId());
        //1.2根本不是当前启动成功阶段该填写字段 默认 charging_capacity charging_duration charging_end_time..
        //1.3支付订单完成才补充字段 pay_amount pay_time..
        //1.4业务数据 bill_status启动成功 正在充电 charging_start_time create_time update_time delete
        success.setBillStatus(1);
        success.setChargingStartTime(new Date());
        success.setCreateTime(success.getChargingStartTime());
        success.setUpdateTime(success.getChargingStartTime());
        success.setDeleted(0);
        //2.调用仓储层写入
        billRepository.saveSuccessBill(success);
    }

    @Override
    public void handleCheckNoRes(DelayCheckMessage msg) {
        //1.封装一个方法 使用订单编号 查询订单是否存在success或者fail
        Boolean exists = billRepository.existsBill(msg.getOrderNo());
        //判断不存在
        if (!exists) {
            log.info("当前检查的订单不存在,所以按照无响应处理");
            //不存在成功 也不存在失败 无响应
            //2.按照失败处理
            saveBillFail(msg);
            //TODO 3.实时推送消息通知 别等了 已经超时了 sorry
            //4.远程调用设备服务 修改枪的状态 TODO
        }
    }

    private void saveBillFail(DelayCheckMessage msg) {
        //1.组织ChargingBillFailPO 对应表 charging_bill_fail
        ChargingBillFailPO fail = new ChargingBillFailPO();
        //1.1从消息直接获取的属性
        fail.setBillId(msg.getOrderNo());
        fail.setFailDesc("无响应失败");
        fail.setUserId(msg.getUserId());
        fail.setGunId(msg.getGunId());
        //TODO 1.2冗余属性可以使用消息数据单独查询封装 operator_id station_id vehicle_id
        //1.3业务生成的默认值
        fail.setCreateTime(new Date());
        fail.setUpdateTime(fail.getCreateTime());
        fail.setDeleted(0);//逻辑删除字段
        //2.数据仓储层入口 写入失败
        billRepository.saveFailBill(fail);
    }

}
